/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.sql;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;

/**
 * Protocol for defining a client that can render results from an JDBC command execution.
 * <p>
 * 
 * @author Mark A. Kobold &lt;mkobold at isqlviewer dot com&gt;
 * @version 1.0
 */
public interface ResultSetRenderer {

    /**
     * Basic initialization method to allocate resource prior to executing a query.
     * <p>
     */
    public void initialize();

    /**
     * Allows the renderer to substitute the variable by name with something else.
     * <p>
     * When an SQL Statement is executed and inline variables in the Jav variable form of ${variable.name} are detect
     * the SQL executor will request a substitution for the variable name.
     * 
     * @param variableName to substitute.
     * @return the value to be substituted for the given variable name.
     */
    public String substituteVariable(String variableName);

    /**
     * Processes ResultSet objects from a statement execution.
     * <p>
     * This is the common method for dispatching a result set for processing outside the database connection object.
     * Once a Statement has executed and has results this method will be invoked. Implementations are not required to
     * nor are they encouraged to close the resultset as the code calling this method should ensure that the resultset
     * is closed properly. If the statement is returning multiple resultsets this method will be called for each
     * resultset recieved. The exception for closing ResultSets is described in the supportsUpdateableResultSets()
     * method.
     * <p>
     * The count parameter is for convience to indicate which resultset this is in a series of resultsets, if the
     * statement is returning only one resultset or is executing a single statement the count should always be 0. There
     * are situations where multiple queries can be executed in a single statement the count parameter in this situation
     * will also represent the resultset count in the series.
     * 
     * @see #supportsUpdateableResultSets()
     * @see Statement#getResultSet()
     * @param nativeSQL SQL that created the given ResultSet.
     * @param stmtID unique identifier for this statement.
     * @param set ResultSet returned from the statement's execution.
     * @param count in the situation of multiple resultsets this will be a counter for the resultset.
     * @return number of rows processed from the result set.
     */
    public long processResultSet(String stmtID, ResultSet set, String nativeSQL, int count);

    /**
     * Processes row updates from a statement execution.
     * <p>
     * If a Statement execution does not return any resultsets then it most likely was an UPDATE or something similar.
     * This allows for notification for the that update count returned by the statement.
     * 
     * @see Statement#getUpdateCount()
     * @param nativeSQL the SQL that created the update count.
     * @param stmtID unique identifier for the executing statement.
     * @param updateCount the update count as a result of statement execution.
     */
    public void processRowUpdates(String stmtID, int updateCount, String nativeSQL);

    /**
     * Process generated keys result set after initial result set is processed.
     * <p>
     * If this ResultSetViewer supports processing generated keys, this method should called if and only the statement
     * provides generated keys resultset. Like the other methods implementations are not required to close the
     * resultset, the invoking code should close the resultset after this method is closed.
     * <p>
     * A Side note that the generated keys is a JDBC 3.0 feature so make sure that the JDBC driver has been updated to
     * be uses in the JDK 1.4.x+ runtimes as the JDK 1.4.x runtimes support the JDBC 3.0 specification.
     * 
     * @see #supportsGeneratedKeys()
     * @see Statement#getGeneratedKeys()
     * @param nativeSQL SQL statement that the keys originated from.
     * @param stmtID unique identifier for this statement.
     * @param keys generated keys as a result of the previous resultset.
     */
    public void processGeneratedKeys(String stmtID, ResultSet keys, String nativeSQL);

    /**
     * Notifcation that the a statement object has been created and is ready to execute.
     * <p>
     * Simple callback method for indicating that the Statement object has been created and will be executing shortly
     * after this method. Implementations can use the stmtID for ensuring each resultset is processed correctly, if
     * implementation are responding to multiple statement executions.
     * 
     * @param stmtID unique identifier for the statement currently executing.
     */
    public void statementInitialized(String stmtID, Statement statement);

    /**
     * Determines if this object wants to view generated keys.
     * <p>
     * If this method returns true, a second call should be made to processGeneratedKeys so that the can be properly
     * handled. Note if there are no generated keys and or they are supported for a paticular JDBC platform.
     * <p>
     * You can check support for generated keys through the DatabaseMetaData object.
     * 
     * @see java.sql.DatabaseMetaData#supportsGetGeneratedKeys()
     * @return true to process generated keys or not process them.
     */
    public boolean supportsGeneratedKeys();

    /**
     * Determining if this resultset viewer can edit updatable resultsets.
     * <p>
     * If a ResultSet is deemed updateable and this method returns true, then the DatabaseConnection object will not
     * automatically close the resultset when it is done processing it. This allows this object to keeps a reference to
     * it and provide updates to the Resultset as needed.
     * <p>
     * If the ResultSet is not updatable or the statement is generating multiple results then the value returned here
     * will be ignored as with multiple resultsets it says in the JDBC API that one and only one resultset should be
     * open per statement object. so with that if multiple results are being returned all results will be automatically
     * closed.
     * <p>
     * Since the resultset is not automatically closed, it is strongly encouraged that extra steps are taken to ensure
     * that a resultset is closed, as open resultsets can cause erratic problems on certain JDBC platforms.
     * 
     * @return if this object can perform updates on the ResultSet.
     */
    public boolean supportsUpdateableResultSets();

    /**
     * Delegates an SQLException from a given ResultSet.
     * <p>
     * If performing some processing of the given ResultSet, results with an SQLException, than it should be delegated
     * here.
     * <p>
     * Code may send a null ResultSet to indicate a general SQLException.
     * 
     * @param set ResultSet as the source of the Exception, can be null.
     * @param e Exception that has occured.
     */
    public void handleSQLException(SQLException e);

    /**
     * handler if the statement has been interrupted or cancelled.
     * <p>
     * if an error occurs in the realm that the statement execution was interuppted threading wise or through the use of
     * the cancel method on the statement this method will be used to indicate that the statement was interrupted and no
     * further processing will be be executed on the statement.
     * <p>
     * Implementations can use the statement identifier to clean up and resources if nessecary, no further calls to this
     * object should be made with the given statement ID, if so exceptions should be thrown.
     * 
     * @param stmtID unqiue identifier for the statement that was cancelled.
     */
    public void finalizeStatement(String stmtID);

    /**
     * Statement warnings from a resultset can be delegated here.
     * <p>
     * Any code that invokes this method should clear all warnings from the given Statement to help insure that the same
     * warning is not processed more than it needs to be.
     * 
     * @param stmt Source statement object the warnings are coming from.
     * @param warnings from a statement.
     */
    public void recieveStatementWarnings(Statement stmt, SQLWarning warnings);

    /**
     * Delegates SQLWarnings from the given ResultSet to be handled.
     * <p>
     * Any code that invokes this method should clear all warnings from the given ResultSet to help insure that the same
     * warning is not processed more than it needs to be.
     * 
     * @param set ResultSet source where the given warnings came from.
     * @param warnings detected from the given resultset.
     */
    public void recieveResultsetWarnings(ResultSet set, SQLWarning warnings);

    /**
     * @return
     */
    public boolean isCancelled();

}
